﻿#include "TransparentPass.h"

#include "../../../Common/Singleton.h"
#include "../ResourceManager/Dx2GeometryManager.h"
#include "../ResourceManager/Dx2MaterialManager.h"
#include "../ResourceManager/Dx2ShaderAndLayoutManager.h"
#include "../ResourceManager/Dx2RootSignatureManager.h"

void TransparentPass::BuildRenderItems(std::vector<std::unique_ptr<RenderItem>>& allRitems,UINT& lastObjIndex)
{
    auto mirrorRitem = std::make_unique<RenderItem>();
    mirrorRitem->World = MathHelper::Identity4x4();
    mirrorRitem->TexTransform = MathHelper::Identity4x4();
    mirrorRitem->ObjCBIndex = lastObjIndex;
    lastObjIndex++;
    mirrorRitem->Mat = Singleton<Dx2MaterialManager>::Instance()->GetMaterial("icemirror").get();
    mirrorRitem->Geo = Singleton<Dx2GeometryManager>::Instance()->GetGeometry("roomGeo").get();
    mirrorRitem->IndexCount = mirrorRitem->Geo->DrawArgs["mirror"].IndexCount;
    mirrorRitem->StartIndexLocation = mirrorRitem->Geo->DrawArgs["mirror"].StartIndexLocation;
    mirrorRitem->BaseVertexLocation = mirrorRitem->Geo->DrawArgs["mirror"].BaseVertexLocation;

    mRenderItems.push_back(mirrorRitem.get());
    allRitems.push_back(move(mirrorRitem));
}

void TransparentPass::BuildPSOs(ID3D12Device* device, DXGI_FORMAT BackBufferFormat, DXGI_FORMAT DepthStencilFormat,
    bool _4xMsaaState, UINT _4xMsaaQuality)
{
    D3D12_GRAPHICS_PIPELINE_STATE_DESC transparentPsoDesc;
    ZeroMemory(&transparentPsoDesc,sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
	
    transparentPsoDesc.InputLayout = {Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetInputLayout().data(),(UINT)Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetInputLayout().size()};
    transparentPsoDesc.pRootSignature = Singleton<Dx2RootSignatureManager>::Instance()->GetRootSignature(RootSignatureType::Default).Get();
	
    transparentPsoDesc.VS =
        {
        reinterpret_cast<BYTE*>(Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetShader("standardVS")->GetBufferPointer()),
        Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetShader("standardVS")->GetBufferSize()
    };
	
    transparentPsoDesc.PS =
        {
        reinterpret_cast<BYTE*>(Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetShader("opaquePS")->GetBufferPointer()),
        Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetShader("opaquePS")->GetBufferSize()
    };
	
    transparentPsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
    transparentPsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
    transparentPsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
    transparentPsoDesc.SampleMask = UINT_MAX;
    transparentPsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
    transparentPsoDesc.NumRenderTargets = 1;
    transparentPsoDesc.RTVFormats[0] = BackBufferFormat;
    transparentPsoDesc.SampleDesc.Count = _4xMsaaState? 4:1;
    transparentPsoDesc.SampleDesc.Quality = _4xMsaaState? (_4xMsaaQuality - 1):0;
    transparentPsoDesc.DSVFormat = DepthStencilFormat;

    D3D12_RENDER_TARGET_BLEND_DESC transparencyBlendDesc;
    transparencyBlendDesc.BlendEnable = true;
    transparencyBlendDesc.LogicOpEnable = false;
    transparencyBlendDesc.SrcBlend = D3D12_BLEND_SRC_ALPHA;
    transparencyBlendDesc.DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
    transparencyBlendDesc.BlendOp = D3D12_BLEND_OP_ADD;
    transparencyBlendDesc.SrcBlendAlpha = D3D12_BLEND_ONE;
    transparencyBlendDesc.DestBlendAlpha = D3D12_BLEND_ZERO;
    transparencyBlendDesc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
    transparencyBlendDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
    transparencyBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
	
    transparentPsoDesc.BlendState.RenderTarget[0] = transparencyBlendDesc;

    ThrowIfFailed(device->CreateGraphicsPipelineState(&transparentPsoDesc,IID_PPV_ARGS(&mPso)));
}

void TransparentPass::Draw(ID3D12GraphicsCommandList* cmdList, CD3DX12_GPU_DESCRIPTOR_HANDLE hGpuHandler,
    UINT srvHeapSize, UINT objCBByteSize, UINT matCBByteSize, UINT passCBByteSize,
     ID3D12Resource* objectCB,ID3D12Resource* matCB, ID3D12Resource* passCB,
     const PassConstants& passValue,
     ID3D12Resource* OutColorRenderTarget,
     D3D12_CPU_DESCRIPTOR_HANDLE OutColorRenderTargetView,
     D3D12_CPU_DESCRIPTOR_HANDLE OutDepthStentilView
  )
{
    cmdList->OMSetStencilRef(0);
    cmdList->SetPipelineState(mPso.Get());
    cmdList->SetGraphicsRootConstantBufferView(2, passCB->GetGPUVirtualAddress());

    DrawRenderItem(cmdList,hGpuHandler,srvHeapSize,objCBByteSize,matCBByteSize,objectCB,matCB,mRenderItems);
}
